#include "../lib_include/Thread.h"
#include "../lib_include/CurrentThread.h"
#include "../lib_include/Exception.h"
#include "../lib_include/Logger.h"

#include <type_traits>
#include <errno.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/prctl.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <linux/unistd.h>

namespace netlib
{

namespace detail
{

class ThreadData;

// 系统调用获得线程tid
pid_t gettid() { return static_cast<pid_t>(::syscall(SYS_gettid)); }

void afterFork() // 子进程中调用，记录子进程中主线程的信息
{
    netlib::CurrentThread::t_cachedTid = 0;
    netlib::CurrentThread::t_threadName = "main";
    CurrentThread::tid();
}

// pthread_atfork(prepare,parent,child)三个函数指针作为参数,系统会在调用fork()前
//调用prepare，调用fork()后父进程调用parent()，子进程调用child()

class ThreadNameInitializer // 创建子进程时发挥作用，记录子进程中主线程有关信息
{
public:
    ThreadNameInitializer()
    {
        netlib::CurrentThread::t_threadName = "main";
        CurrentThread::tid();
        pthread_atfork(NULL, NULL, &afterFork);
    }
};

ThreadNameInitializer init;

struct ThreadData // Thread的内嵌类，用于安全执行线程函数，处理异常
{
    typedef netlib::Thread::ThreadFunc ThreadFunc;
    ThreadFunc func_;           // 回调函数
    string name_;               // 线程名称
    pid_t* tid_;                // 线程全局标识符tid
    CountDownLatch* latch_;     // 倒计时同步类

    ThreadData(ThreadFunc func,
                const string& name,
                pid_t* tid,
                CountDownLatch* latch)
        : func_(std::move(func)),
        name_(name),
        tid_(tid),
        latch_(latch)
    { }

    void runInThread() // 真正执行线程函数的主体，存在异常处理
    {
        *tid_ = netlib::CurrentThread::tid();    // 获取线程tid，并缓存
        tid_ = NULL;                            // 使用完置空
        latch_->countDown();                    // 计数器减1
        latch_ = NULL;                          // 使用完置空

        netlib::CurrentThread::t_threadName = name_.empty() ? "netlibThread" : name_.c_str();
        ::prctl(PR_SET_NAME, netlib::CurrentThread::t_threadName);

        try
        {
            func_(); // 线程真正的执行函数
            netlib::CurrentThread::t_threadName = "finished";
        }
        catch (const Exception& ex)
        {
            netlib::CurrentThread::t_threadName = "crashed";
            fprintf(stderr, "exception caught in Thread %s\n", name_.c_str());
            fprintf(stderr, "reason: %s\n", ex.what());
            fprintf(stderr, "stack trace: %s\n", ex.stackTrace());
            abort();
        }
        catch (const std::exception& ex)
        {
            netlib::CurrentThread::t_threadName = "crashed";
            fprintf(stderr, "exception caught in Thread %s\n", name_.c_str());
            fprintf(stderr, "reason: %s\n", ex.what());
            abort();
        }
        catch (...)
        {
            netlib::CurrentThread::t_threadName = "crashed";
            fprintf(stderr, "unknown exception caught in Thread %s\n", name_.c_str());
            throw; // rethrow
        }
    }

}; // struct ThreadData end

void* startThread(void* obj) // pthread_create线程入口函数
{
    ThreadData* data = static_cast<ThreadData*>(obj);
    data->runInThread(); // 执行线程函数的入口
    delete data;
    return NULL;
}

} // namespace detail end


void CurrentThread::cacheTid() // 获取线程tid
{
    if (t_cachedTid == 0)
    {
        t_cachedTid = detail::gettid(); // 系统调用获得tid
        t_tidStringLength = snprintf(t_tidString, sizeof t_tidString, "%5d ", t_cachedTid);
    }
}

// 判断当前线程是否为主线程
bool CurrentThread::isMainThread() { return tid() == ::getpid(); }

// 线程休眠usec秒
void CurrentThread::sleepUsec(int64_t usec)
{
    struct timespec ts = { 0, 0 };
    ts.tv_sec = static_cast<time_t>(usec / Timestamp::kMicroSecondsPerSecond);
    ts.tv_nsec = static_cast<long>(usec % Timestamp::kMicroSecondsPerSecond * 1000);
    ::nanosleep(&ts, NULL);
}

AtomicInt32 Thread::numCreated_;

Thread::Thread(ThreadFunc func, const string& n)
  : started_(false),
    joined_(false),
    pthreadId_(0),
    tid_(0),
    func_(std::move(func)),
    name_(n),
    latch_(1)
{ setDefaultName(); } // 构造中调用初始化函数

Thread::~Thread()
{
    if (started_ && !joined_)
        pthread_detach(pthreadId_);
}

void Thread::setDefaultName() // 初始化线程编号名称、原子计数自增
{
    int num = numCreated_.incrementAndGet();
    if (name_.empty())
    {
        char buf[32];
        snprintf(buf, sizeof buf, "Thread%d", num);
        name_ = buf;
    }
}

void Thread::start() // 开启线程
{
    assert(!started_);
    started_ = true;
    detail::ThreadData* data = new detail::ThreadData(func_, name_, &tid_, &latch_);
    if (pthread_create(&pthreadId_, NULL, &detail::startThread, data))
    {
        started_ = false;
        delete data;
        LOG_SYSFATAL << "Failed in pthread_create";
    }
    else
    {
        latch_.wait(); // 主线程等待子线程运行到执行函数入口，计数器减至0，主线程继续运行
        assert(tid_ > 0);
    }
}

int Thread::join() // 线程开启join()
{
    assert(started_);
    assert(!joined_);
    joined_ = true;
    return pthread_join(pthreadId_, NULL);
}

} // namespace netlib end
